bitkeeper revision 1.652.2.1 (3fe4dd99t24zD9Wu1VbWDg5fOnRCgQ)
authoriap10@nidd.cl.cam.ac.uk <iap10@nidd.cl.cam.ac.uk>
Sat, 20 Dec 2003 23:39:05 +0000 (23:39 +0000)
committeriap10@nidd.cl.cam.ac.uk <iap10@nidd.cl.cam.ac.uk>
Sat, 20 Dec 2003 23:39:05 +0000 (23:39 +0000)
Cleanup and documentation improvement to createlinuxdom.py/XenoUtil.py
along with addition of VM auto restart facility (latter curtesy of
Mark Williamson).

.rootkeys
BitKeeper/etc/logging_ok
tools/examples/createlinuxdom.py
tools/examples/mynewdom.py [deleted file]
tools/xc/lib/Makefile
tools/xc/py/XenoUtil.py

index 8506a8fff808bdf124816eb5aabcd14761a2966e..bbc5d2ac78e80c9cee6e8dd4a0fd4dc6a70feb87 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
@@ -42,7 +42,6 @@
 3fbe2f12OPAkzIUtumU3wRAihnhocQ tools/examples/createlinuxdom.py
 3fbe2f12dZbmXLlgQdMgkmnSUj23AQ tools/examples/destroydom.py
 3fbe2f12ltvweb13kBSsxqzZDAq4sg tools/examples/listdoms.py
-3fca7788tBihusQSq3HJI-YKQTN2iQ tools/examples/mynewdom.py
 3fca7700PVj36cZObaFZlQicRiw1pQ tools/examples/pincpu.py
 3fd8bc48ww3aOqPhYjCr8KGulG0NQQ tools/examples/readxenconsolering.py
 3fccbe068ov0YCxnk-2m4law19QMmA tools/examples/startdom.py
index 461b17a97a28ab6c9668b94efa4145144bede67a..da1235fdb003ef4a5bf7bbb2b4a8cf2213b7712f 100644 (file)
@@ -10,6 +10,7 @@ br260@labyrinth.cl.cam.ac.uk
 br260@laudney.cl.cam.ac.uk
 iap10@freefall.cl.cam.ac.uk
 iap10@labyrinth.cl.cam.ac.uk
+iap10@nidd.cl.cam.ac.uk
 iap10@striker.cl.cam.ac.uk
 jws22@gauntlet.cl.cam.ac.uk
 jws@cairnwell.research
index d01a2ea0b7c7e80cf2d81bfe80ccb99ab55733d8..e183b422f8b6358d8ef74c56e256c26899c60033 100755 (executable)
 
 #
 # Example script for creating and building a new Linux guest OS for Xen.
+# It takes an optional parameter that specifies offsets to be added to the
+# ip address and root partition numbers, enabling multiple domains to be
+# started from the one script.
+#
+# Edit as required...
 #
 
-import Xc, XenoUtil, sys, os
+import Xc, XenoUtil, string, sys, os, time, socket
 
-# Variable declaration. Set these up properly later on, as needed.
-nfsserv = nfspath = root_partn = usr_partn = ""
+# initialize a few variables that might come in handy
+thishostname = socket.gethostname()
+guestid = 0
+if sys.argv >= 2:
+    guestid = string.atoi(sys.argv[1])
+    print "Offset to add to guest's IP etc : %d\n" % guestid
+##### This section of the code establishes various settings to be used 
+##### for this guest virtual machine
 
-# STEP 1. Specify kernel image file.
-image = "FULL_PATH_TO_IMAGE"
+# STEP 1. Specify kernel image file. Can be gzip'ed.
+image = "../../../install/boot/xenolinux.gz"
 
 # STEP 2. How many megabytes of memory for the new domain?
 memory_megabytes = 64
 
 # STEP 3. A handy name for your new domain.
-domain_name = "My new domain"
+domain_name = "This is VM %d" % guestid
+
+# STEP 4. Specify IP address(es), netmask and gateway for the new
+# domain.  You need to configure IP addrs within the domain just as
+# you do normally.  This is just to let Xen know about them so it can
+# route packets appropriately. 
 
-# STEP 4. Specify IP address, netmask and gateway for the new domain.
-ipaddr  = "ADDRESS"
+#ipaddr = ["111.222.333.444","222.333.444.555"]
+ipaddr  = [XenoUtil.add_offset_to_ip(XenoUtil.get_current_ipaddr(),guestid)]
 netmask = XenoUtil.get_current_ipmask()
 gateway = XenoUtil.get_current_ipgw()
+nfsserv = '169.254.1.0'  # You need to set this if you're using NFS root
 
-# STEP 5a. Specify NFS server and path to rootfs (only needed for network boot)
-nfsserv = "ADDRESS"
-nfspath = "FULL_PATH_TO_ROOT_DIR"
-
-# STEP 5b. Specify root partition on local disc (if not NFS booting)
-#root_partn = "/dev/sda2"
-# (NB. The following is only needed for a separate shared read-only /usr)
-# (usr_partn  = "/dev/sda6")
-
-# STEP 6. Check that the following cmdline setup is to your taste.
-cmdline = "ip="+ipaddr+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
-if root_partn:
-    # Boot from local disc. May specify a separate /usr.
-    cmdline = cmdline + " root="+root_partn+" ro"
-    if usr_partn:
-        " usr="+usr_partn
-elif nfsserv:
-    # NFS boot
-    cmdline = cmdline + " root=/dev/nfs"
-    cmdline = cmdline + " nfsroot="+nfspath
-
-if root_partn:
-    root_info = XenoUtil.lookup_blkdev_partn_info(root_partn)
-    if not root_info:
-        print "Could not obtain info on partition '" + root_partn + "'"
-        sys.exit()
+# STEP 5. Identify any physcial partitions or virtual disks you want the
+# domain to have access to, and what you want them accessible as
+# e.g. vbds = [ ('phy:sda1','sda1', 'w'),
+#       ('phy:sda4','sda%d' % (3+guestid), 'r'), 
+#       ('vd:as73gd784dh','hda1','w') ]
 
-if usr_partn:
-    usr_info = XenoUtil.lookup_blkdev_partn_info(usr_partn)
-    if not usr_info:
-        print "Could not obtain info on partition '" + usr_partn + "'"
-        sys.exit()
+vbds = [ ('phy:sda%d'%(7+guestid),'sda1','w' ), 
+        ('phy:sda6','sda6','r'),
+        ('phy:cdrom','hdd','r') ]
 
-if not os.path.isfile( image ):
-    print "Image file '" + image + "' does not exist"
-    sys.exit()
+# STEP 6. Build the command line for the new domain. Edit as req'd.
+# You only need the ip= line if you're NFS booting or the root file system
+# doesn't set it later e.g. in ifcfg-eth0 or via DHCP
+# You can use 'extrabit' to set the runlevel and custom environment
+# variables used by custom rc scripts (e.g. DOMID=, usr= )
 
-xc = Xc.new()
+ipbit = "ip="+ipaddr[0]+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
+rootbit = "root=/dev/sda1 ro"
+#rootbit = "root=/dev/nfs nfsroot=/full/path/to/root/directory"
+extrabit = "4 DOMID=%d usr=/dev/sda6" % guestid 
+cmdline = ipbit +" "+ rootbit +" "+ extrabit
 
-id = xc.domain_create( mem_kb=memory_megabytes*1024, name=domain_name )
-if id <= 0:
-    print "Error creating domain"
-    sys.exit()
+# STEP 7. Set according to whether you want the script to watch the domain 
+# and auto-restart it should it die or exit.
 
-if xc.linux_build( dom=id, image=image, cmdline=cmdline ):
-    print "Error building Linux guest OS"
-    xc.domain_destroy ( dom=id )
-    sys.exit()
+auto_restart = False
+#auto_restart = True
 
-if root_partn:
-    if xc.vbd_create( dom=id, vbd=root_info[0], writeable=1 ):
-        print "Error creating root VBD"
-        xc.domain_destroy ( dom=id )
+
+##### Print some debug info just incase things don't work out...
+##### 
+
+print "Domain image          : ", image
+print "Domain memory         : ", memory_megabytes
+print "Domain IP address(es) : ", ipaddr 
+print "Domain block devices  : ", vbds
+print 'Domain cmdline        : "%s"' % cmdline
+
+
+##### Code beyond this point is actually used to manage the mechanics of
+##### starting (and watching if necessary) guest virtual machines.
+
+# Obtain an instance of the Xen control interface
+xc = Xc.new()
+
+# This function creates, builds and starts a domain, using the values
+# in the global variables, set above.  It is used in the subsequent
+# code for starting the new domain and rebooting it if appropriate.
+def make_domain():
+    """Create, build and start a domain.
+    Returns: [int] the ID of the new domain.
+    """
+
+    # set up access to the global variables declared above
+    global image, memory_megabytes, domain_name, ipaddr, netmask
+    global vbds, cmdline, xc
+       
+    if not os.path.isfile( image ):
+        print "Image file '" + image + "' does not exist"
         sys.exit()
-    if xc.vbd_grow( dom=id,
-                    vbd=root_info[0],
-                    device=root_info[1],
-                    start_sector=root_info[2],
-                    nr_sectors=root_info[3] ):
-        print "Error populating root VBD"
-        xc.domain_destroy ( dom=id )
+
+    id = xc.domain_create( mem_kb=memory_megabytes*1024, name=domain_name )
+    print "Created new domain with id = " + str(id)
+    if id <= 0:
+        print "Error creating domain"
         sys.exit()
 
-if usr_partn:
-    if xc.vbd_create( dom=id, vbd=usr_info[0], writeable=0 ):
-        print "Error creating usr VBD"
+    ret = xc.linux_build( dom=id, image=image, cmdline=cmdline )
+    if ret < 0:
+        print "Error building Linux guest OS: "
+        print "Return code from linux_build = " + str(ret)
         xc.domain_destroy ( dom=id )
         sys.exit()
-    if xc.vbd_grow( dom=id,
-                    vbd=usr_info[0],
-                    device=usr_info[1],
-                    start_sector=usr_info[2],
-                    nr_sectors=usr_info[3] ):
-        print "Error populating usr VBD"
+
+    # setup the virtual block devices
+    for ( uname, virt_name, rw ) in vbds:
+       virt_dev = XenoUtil.blkdev_name_to_number( virt_name )
+
+       segments = XenoUtil.lookup_disk_uname( uname )
+       if not segments:
+           print "Error looking up %s\n" % uname
+           xc.domain_destroy ( dom=id )
+           sys.exit()
+
+       if xc.vbd_create( dom=id, vbd=virt_dev, writeable= rw=='w' ):
+           print "Error creating VBD vbd=%d writeable=%d\n" % (virt_dev,rw)
+           xc.domain_destroy ( dom=id )
+           sys.exit()
+
+       for (s_dev,s_start,s_len,s_type) in segments:
+           if xc.vbd_grow( dom=id,
+                           vbd=virt_dev,
+                           device=s_dev,
+                           start_sector=s_start,
+                           nr_sectors=s_len ):
+               print "Error populating VBD vbd=%d\n" % virt_dev
+               xc.domain_destroy ( dom=id )
+               sys.exit()
+
+    # setup virtual firewall rules for all aliases
+    for ip in ipaddr:
+       XenoUtil.setup_vfr_rules_for_vif( id, 0, ip )
+
+    if xc.domain_start( dom=id ) < 0:
+        print "Error starting domain"
         xc.domain_destroy ( dom=id )
         sys.exit()
 
-XenoUtil.setup_vfr_rules_for_vif( id, 0, ipaddr )
+    return id
+# end of make_domain()
+
+
+
+# The starting / monitoring of the domain actually happens here...
+
+# start the domain and record its ID number
+current_id = make_domain()
+
+# if the auto_restart flag is set then keep polling to see if the domain is
+# alive - restart if it is not by calling make_domain() again (it's necessary
+# to update the id variable, since the new domain may have a new ID)
 
-if xc.domain_start( dom=id ):
-    print "Error starting domain"
-    xc.domain_destroy ( dom=id )
-    sys.exit()
+while auto_restart:
+    time.sleep(1)
+    if not xc.domain_getinfo(current_id):
+        print "The virtual machine has terminated, restarting in a new domain"
+        current_id = make_domain()
diff --git a/tools/examples/mynewdom.py b/tools/examples/mynewdom.py
deleted file mode 100755 (executable)
index 29c8a35..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env python
-
-# Example script for creating and building a new Linux guest OS for
-# Xen.  THIS IS VERY SITE SPECIFIC, but shows an example configuration
-# using multiple root partitions with a common /usr.  e.g. Domain1
-# uses root /dev/sda8, usr /dev/sda6, and the next sequential IP address.
-
-import Xc, XenoUtil, sys, os, socket, re
-
-# Variable declaration. Set these up properly later on, as needed.
-nfsserv = nfspath = root_partn = usr_partn = ""
-shost = re.search( '([a-zA-Z]+)[-.]', socket.gethostname() ).group(1)
-
-# STEP 1. Specify kernel image file.
-image = "/usr/groups/srgboot/%s/xenolinux.gz" % shost
-
-# STEP 2. How many megabytes of memory for the new domain?
-memory_megabytes = 64
-
-# STEP 3. A handy name for your new domain.
-domain_name = "My new domain"
-
-# Allocate new domain ad get its domain id
-xc = Xc.new()
-id = xc.domain_create( mem_kb=memory_megabytes*1024, name=domain_name )
-if id <= 0:
-    print "Error creating domain"
-    sys.exit()
-
-# Set the CPU, or leave to round robin allocation
-#xc.domain_pincpu( dom=id, cpu=1 )
-
-# STEP 4. Specify IP address, netmask and gateway for the new domain.
-ipaddr  = XenoUtil.add_offset_to_ip(XenoUtil.get_current_ipaddr(),id)
-netmask = XenoUtil.get_current_ipmask()
-gateway = XenoUtil.get_current_ipgw()
-
-# STEP 5a. Specify NFS server and path to rootfs (only needed for network boot)
-#nfsserv = "ADDRESS"
-#nfspath = "FULL_PATH_TO_ROOT_DIR"
-
-# STEP 5b. Specify root partition on local disc (if not NFS booting)
-root_partn = "/dev/sda%d" % (7+id)
-# (NB. The following is only needed for a separate shared read-only /usr)
-usr_partn  = "/dev/sda6"
-
-# STEP 6. Check that the following cmdline setup is to your taste.
-cmdline = "ip="+ipaddr+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
-if root_partn:
-    # Boot from local disc. May specify a separate /usr.
-    cmdline = cmdline + " root="+root_partn+" ro"
-    if usr_partn:
-        " usr="+usr_partn
-elif nfsserv:
-    # NFS boot
-    cmdline = cmdline + " root=/dev/nfs"
-    cmdline = cmdline + " nfsroot="+nfspath
-
-if root_partn:
-    root_info = XenoUtil.lookup_blkdev_partn_info(root_partn)
-    if not root_info:
-        print "Could not obtain info on partition '" + root_partn + "'"
-        sys.exit()
-
-if usr_partn:
-    usr_info = XenoUtil.lookup_blkdev_partn_info(usr_partn)
-    if not usr_info:
-        print "Could not obtain info on partition '" + usr_partn + "'"
-        sys.exit()
-
-if not os.path.isfile( image ):
-    print "Image file '" + image + "' does not exist"
-    sys.exit()
-
-
-if xc.linux_build( dom=id, image=image, cmdline=cmdline ):
-    print "Error building Linux guest OS"
-    xc.domain_destroy ( dom=id )
-    sys.exit()
-
-if root_partn:
-    if xc.vbd_create( dom=id, vbd=root_info[0], writeable=1 ):
-        print "Error creating root VBD"
-        xc.domain_destroy ( dom=id )
-        sys.exit()
-    if xc.vbd_grow( dom=id,
-                    vbd=root_info[0],
-                    device=root_info[1],
-                    start_sector=root_info[2],
-                    nr_sectors=root_info[3] ):
-        print "Error populating root VBD"
-        xc.domain_destroy ( dom=id )
-        sys.exit()
-
-if usr_partn:
-    if xc.vbd_create( dom=id, vbd=usr_info[0], writeable=0 ):
-        print "Error creating usr VBD"
-        xc.domain_destroy ( dom=id )
-        sys.exit()
-    if xc.vbd_grow( dom=id,
-                    vbd=usr_info[0],
-                    device=usr_info[1],
-                    start_sector=usr_info[2],
-                    nr_sectors=usr_info[3] ):
-        print "Error populating usr VBD"
-        xc.domain_destroy ( dom=id )
-        sys.exit()
-
-XenoUtil.setup_vfr_rules_for_vif( id, 0, ipaddr )
-
-if xc.domain_start( dom=id ):
-    print "Error starting domain"
-    xc.domain_destroy ( dom=id )
-    sys.exit()
index c19643e8fbe706b11e73ba0d0071ca7583ce9627..2693372048f71f58bd5844d519b97921bf777b37 100644 (file)
@@ -22,7 +22,7 @@ install: all
        mkdir -p /usr/lib
        mkdir -p /usr/include
        cp -a $(LIB) /usr/lib
-       chmod 755 /usr/bin/$(LIB)
+       chmod 755 /usr/lib/$(LIB)
        cp -a xc.h /usr/include
        chmod 644 /usr/include/xc.h
 
@@ -30,7 +30,7 @@ dist: all
        mkdir -p ../../../../install/lib
        mkdir -p ../../../../install/include
        cp -a $(LIB) ../../../../install/lib
-       chmod 755 ../../../../install/bin/$(LIB)
+       chmod 755 ../../../../install/lib/$(LIB)
        cp -a xc.h ../../../../install/include
        chmod 644 ../../../../install/include/xc.h
 
index 850dd8ddb487d5ab2b82205d93537733a436f26b..81fca35e475f2f108a6d13660b41e467c8f4bee6 100644 (file)
@@ -12,7 +12,7 @@ def blkdev_name_to_number(name):
 
 
 # lookup_blkdev_partn_info( '/dev/sda3' )
-def lookup_blkdev_partn_info(partition):
+def lookup_raw_partn(partition):
     """Take the given block-device name (e.g., '/dev/sda1', 'hda')
     and return a information tuple ( partn-dev, disc-dev, start-sect,
     nr-sects, type )
@@ -32,11 +32,10 @@ def lookup_blkdev_partn_info(partition):
         fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
         line = fd.readline()
         if line:
-            return ( blkdev_name_to_number(drive),
-                     blkdev_name_to_number(drive),
+            return [( blkdev_name_to_number(drive),
                      0,
                      string.atol(line) * 2,
-                     'Disk' )
+                     'Disk' )]
         return None
 
     # determine position on disk
@@ -48,13 +47,21 @@ def lookup_blkdev_partn_info(partition):
         m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
                        'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
         if m:
-            return ( blkdev_name_to_number(partition),
-                     blkdev_name_to_number(drive),
+            return [( blkdev_name_to_number(drive),
                      string.atol(m.group(1)),
                      string.atol(m.group(2)),
-                     m.group(3) )
+                     m.group(3) )]
     return None
 
+def lookup_disk_uname( uname ):
+    ( type, d_name ) = string.split( uname, ':' )
+
+    if type == "phy":
+       segments = lookup_raw_partn( d_name )
+    elif type == "vd":
+       segments = lookup_vd( d_name )
+
+    return segments
 
 def get_current_ipaddr(dev='eth0'):
     """Return a string containing the primary IP address for the given